home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-01-24 | 44.9 KB | 1,100 lines |
-
- QLIB library version 1.2 for the QuickBASIC compiler
- (c) 1988 Douglas Herr
-
- WHY USE QLIB?
-
- QuickBASIC represents an enormous leap in BASIC programming over
- interpreted BASICA or GWBASIC, and is a language that many programmers
- already know. However, many programmers also know that many QuickBASIC
- commands are not all that quick, can be extremely cumbersome, and/or
- will hog tremendous amounts of memory. QLIB is a library of Assembly-
- language subroutines which provides quick, compact solutions to many of
- QuickBASIC's problems.
-
- Many of QLIB's routines grew out of my own frustration with QuickBASIC's
- deficiencies, particularly QuickBASIC's meager support of the Hercules
- video graphics card. Each QLIB routine has been tested extensively, but
- since I cannot foresee every possible use or abuse of QLIB, I cannot be
- held responsible for any damages resulting from its use.
-
- Ideas for these routines come from a wide variety of sources. If you want
- to see additional routines, let me hear about it.
-
-
- DISTRIBUTION and REGISTRATION
-
- QLIB is NOT public-domain software. This library is distributed using
- the shareware concept. Shareware is high-quality software written by
- people like me who would rather spend their time programming than setting
- up marketing channels. Shareware is the ultimate in try-before-you-buy.
- If you don't like QLIB after trying it, don't register. If you do like
- it, tell me by registering! The shareware concept doesn't work if users
- don't support programmers' efforts.
-
- QLIB is an evolving library, so it is likely that by the time you read
- this there will be several additional routines available. Areas I'm
- particularly working on include 8087 support and Hercules graphics for
- ALL versions of QuickBASIC. Registered users receive the latest version
- of QLIB available when they register, and may upgrade at any time for
- the paltry fee of $10.00.
-
- QLIB may be freely distributed in un-altered form EXCEPT FOR THE SOURCE
- CODE, and remains my property. You may use QLIB on a trial basis, but
- you are expected to register if you intend to use it regularly or include
- QLIB routines in your applications. No royalties are required and
- registration costs only $25, so it makes little sense to not register.
-
- Register by sending $25 to:
-
- Douglas R. Herr
- 2026 Marina Court
- San Leandro, CA 94577
- (415) 351-4779
- Any questions or problems should be sent to me at the same address.
- Please include a stamped, self-addressed envelope if you are not a
- registered user. If you call, more than likely you will talk to
- Iza the Answering Machine.
-
-
- HOW DO I USE QLIB?
-
- QLIB was developed for QuickBASIC 4, but many QLIB routines may be used
- with earlier versions of QuickBASIC. I have tested many routines with
- QuickBASIC 3, and these routines should work equally well with QB2. As
- of this release, I have not tested QLIB with QB3's QB87. QB2 and QB3
- users should read Appendix C - QLIB and QB3.
-
- QLIB may be used with QuickBASIC 4 by copying QLIB.QLB and
- QLIB.LIB to your QuickBASIC directory. (QB3 users should
- use QLIB.EXE in place of QLIB.QLB.)
-
- To load QLIB with the QuickBASIC editor, use the command
-
- QB /L QLIB.QLB
-
- Link QLIB with your object files with
-
- LINK /EX /NOE yourprog,,NUL,QLIB.LIB;
-
- for QB3:
- LINK yourprog,,NUL,QLIB.LIB;
-
- As time permits, QLIB subroutines will be tested and modified, if needed,
- to work with QB3 and QB87. I have clearly noted in this documentation
- any problems I have found.
-
- QLIB VIDEO routines give your applications more control over the
- display screen than QuickBASIC allows. You can save and restore
- screen displays, print to the screen at blinding speed, and use screen
- color attributes not possible with QuickBASIC alone.
-
- Two kinds of QLIB video routines are available: Direct Video Memory
- Transfer (DVMT), the fastest available, and BIOS, compatible with a wider
- range of hardware and software.
-
- BIOS video routines use the PC's BIOS and are slower than DVMT routines,
- but are often faster or more flexible than comparable QuickBASIC commands.
-
- DVMT video subroutines take advantage of PC video systems' known video
- memory addresses and transfer data directly to video memory instead of
- working through DOS or the PC BIOS. This results in nearly instant video
- displays. DVMT also provides additional support for the Hercules
- Graphics Card not available through the PC BIOS. Caution: DVMT subroutines
- may not work properly on PCs which are not close copies of the IBM PC.
- Most PC clones are close copies of the IBM computers. In fact, QLIB's
- DVMT video routines were developed using a cheap XT clone and a
- Hercules-clone monochrome graphics card.
-
- Video hardware configurations supported include Monochrome Display Adapter
- (MDA), Color Display Adapter (CGA), Hercules Graphics Card (HGC), EGA,
- MCGA and VGA. I have used these routines with MDA, HGC and EGA systems.
-
- SCREEN PAGES in text mode may be used with all supported video systems
- except the IBM (or compatible) Monochrome Display Adapter. With CGA
- displays, 4 screen pages are available, and with Hercules (or compatible)
- up to 16 pages may be used with DVMT routines. For EGA, VGA and
- MCGA systems, QLIB supports up to 8 pages. Screen pages may be used to
- store help screens or to save one (or more) screens while another is
- displayed.
-
- CGA screen pages are numbered 0 through 3, and EGA/VGA/MCGA pages
- are numbered 0 through 7. Hercules screen page numbers may be between
- 0 and 15. Even-numbered pages (0 - 14) may be used at any time, but
- odd-numbered pages (1 - 15) may be used only when the second 32k of
- Hercules memory is included in the memory map (see HPage).
- NOTE: BIOS routines support only page 0 on Hercules systems.
- Subroutine: CalcATTR(foreground%, background%, bright%, blink%, ATTR%)
-
- Calculates the color attribute (ATTR%) for many QLIB video
- routines. CalcATTR allows use of the "blink" attribute, which may also
- be used for high-intensity backgrounds. (See SetBLINK.)
-
- Bright% affects only the foreground color, while blink% either makes the
- character blink or causes non-black backgrounds to be bright, depending
- on the last call to SetBLINK. CalcATTR may be used with either BIOS or
- DVMT video routines. See Appendix A, "Color Attributes".
-
- Example:
- CALL CALCATTR(foreground%, background%, bright%, blink%, ATTR%)
-
-
-
- Subroutine: SetBLINK(a%)
-
- Enables / disables blinking attributes in text mode. When blinking
- is disabled, blinking reverse video attributes are changed from normal
- intensity backgrounds to high intensity. SetBLINK affects all screen
- pages. SetBLINK uses BIOS calls for EGA, MCGA and VGA systems, and uses
- DVMT for Monochrome, Hercules and CGA.
-
- Example:
- a% = 0
- CALL SetBLINK(a%) ' turn blink off, high intensity backgrounds on
- a% = 1
- CALL SetBLINK(a%) ' restore blinking attributes
-
-
-
- Subroutine: Bprint(st$, row%, col%, attr%)
- Subroutine: BprintL(st$, row%, col%, attr%)
- Subroutine: BprintU(st$, row%, col%, attr%)
-
- Uses BIOS calls to print a string on the active video page, allowing
- ALL ASCII characters (unlike QuickBASIC's PRINT command). You must
- specify row and column starting position, and color attribute. Does not
- affect cursor position. Bprint is slower than Qprint, below. Bprint
- should be more usable than Qprint in multi-task enviornments and will be
- compatible with some hardware which is not an exact clone of IBM's PC, XT
- or AT. Color attribute may be calculated with CalcATTR.
-
- Bprint may also be used in Graphics modes, but the color attribute may
- not work as expected.
-
- BprintL prints A - Z in lower case a - z without changing st$, and
- BprintU prints a - z in upper case A - Z without changing st$.
-
- Example:
- st$="This is a test of screen printing with BIOS calls"
- row%=10: col%=20
- CALL Bprint(st$, row%, col%, attr%) Subroutine: ClrBlockB(row0%, col0%, row1%, col1%, attr%)
-
- Uses BIOS calls to clear a window of the screen from row0%,
- col0%, to row1%, col1%, where row1% > row0%, col1% > col0%, where row%
- is between 1 and 25 and col% is between 1 and 80. The window may be
- cleared to any color attribute. Color attributes may be calculated using
- CalcATTR. See also Scroll.
-
- Example:
- CALL ClrBlockB(row0%, col0%, row1%, col1%, attr%)
-
-
-
- Subroutine: MaxTextPage(page%)
-
- Uses BIOS calls to determine maximum screen page available to
- BIOS video subroutines (Text mode). Minimum page number is always 0.
-
- Example:
- CALL MaxTextPage(page%)
- REM if page% = 0, then MDA or HGC installed
- REM if page% = 3, then CGA installed
- REM if page% = 7, then EGA, MCGA or VGA installed
-
-
-
- Subroutine: Scroll(row0%, col0%, row1%, col1%, attr%, lines%)
-
- Uses BIOS calls to scroll a window of the screen lines% rows,
- limited by row0%, col0%, row1%, col1%. Positive values of lines% will
- scroll the screen up, negative values scroll the screen down, and lines%
- = 0 will blank the window. Rows cleared by the scrolling action will be
- set to color attribute attr%. Scroll may also be used in graphics modes,
- but the color attribute may not work as expected. Color attributes for
- graphics mode use of Scroll should be background colors only.
-
- Example:
- row0% = 5: col0% = 10: row1% = 15: col1% = 75: lines% = 1
- CALL Scroll(row0%, col0%, row1%, col1%, attr%, lines%)
- REM we just scrolled a window up one row
-
-
-
- Subroutine: TextPage(page%)
-
- Uses BIOS calls to set text mode screen page. Does NOT affect
- QuickBASIC's PRINT command, or DVMT routines. LOCATE may be used, and
- LOCATE commands will be saved when changing screen pages via TextPage.
- Use MaxTextPage to determine maximum page number available.
- NOTE: Hercules screen pages other than 0 are not supported by BIOS-call
- subroutines.
-
- Example:
- CALL TextPage(page%)DVMT video routines, below, are much faster than comparable BIOS video routines
- or QuickBASIC. In most cases, DVMT routines require hardware which is 100%
- compatible with the IBM PC (as are most clones).
-
- Subroutine: ClrBlock(row0%, col0%, row1%, col1%, attr%)
-
- Uses DVMT to clear a window of the screen from row0%, col0%, to
- row1%, col1%, where row1% > row0%, col1% > col0%, where row% is between
- 1 and 25 and col% is between 1 and 80. The window may be cleared to any
- color attribute. Color attributes may be calculated using CalcATTR.
- ClrBlock works with SetQPage. See also QScroll.
-
- Example:
- CALL ClrBlock(row0%, col0%, row1%, col1%, attr%)
-
-
-
- Subroutine: ClrScreen(attr%)
-
- Clears the video page set by SetQPage to a specified color attribute.
- Page cleared is determined by the last SetQPage call, and color attributes
- may be calculated using CalcATTR.
-
- Example:
- CALL ClrScreen(attr%)
-
-
- Subroutine: CopyScreen(frompage%, topage%, oops%)
-
- Copies one page of video memory to another. This may be used
- to save screens to recall later. Oops% will be set to -1 if the
- display adapter is an MDA or if frompage% = topage%. For MDA systems,
- use SaveScreen.
-
- All screen pages saved by CopyScreen are erased when the system is
- set to Graphics mode. Use SaveScreen to save text screens before the
- system is used in Graphics mode.
-
- Example:
- CALL CopyScreen(frompage%, topage%, OOPS%) Subroutine: HPage(page%)
-
- HPage masks the second 32k block of Hercules memory in or out of
- the memory map. If the second 32k is included in the memory map, QLIB's
- video routines can use all Hercules screen pages. The second 32k of
- Hercules video memory conflicts with most color monitors' address space,
- so HPage should be used to mask the second 32k out of the memory map for
- two-monitor systems. Page% = 0 masks the second 32k out of memory, any
- other value of Page% allows the second block.
-
- Example: CALL HPage(page%)
-
-
-
- Subroutine: PaintWindow(row0%, col0%, row1%, col1%, attr%)
-
- DVMT routine which changes the color attribute on a block of the
- active video page defined by row0%, col0%, row1%, col1%. The entire block
- is changed to attr%. Changes color on video page set by SetQPage.
-
- Example:
- row0% = 1
- col0% = 1
- row1% = 25
- col1% = 80
- CALL PaintWindow(row0%, col0%, row1%, col1%, attr%)
- REM we just changed the entire screen to color attr% without
- REM re-printing the text
-
- THE QPRINT SERIES
-
- QuickPRINT DVMT routines print a string of text on the screen at very
- high speed. When used on CGA monitors, QPRINT routines slow down a bit
- to avoid annoying "snow". QPRINT routines include built-in LOCATE and
- COLOR statements, and do not affect the cursor position. ALL ASCII
- characters may be used, but QPRINT routines work only in text mode.
- Color attributes may be calculated with CalcATTR. Use SetQPage to set
- QPRINT's active page. All QPRINT subroutines require an 80-column screen.
-
-
- Subroutine: Qprint(st$, row%, col%, attr%)
- Subroutine: QprintU(st$, row%, col%, attr%)
- Subroutine: QprintL(st$, row%, col%, attr%)
- Subroutine: QprintCE(st$, row%, col%, attr%)
-
- Qprint, the fastest and most compact of the QPRINT series, will
- meet most needs. QprintU will print a-z as upper case A-Z, and QprintL
- will print A-Z as lower case a-z without changing st$. QprintCE clears
- the screen from the end of st$ to the edge of the screen.
-
- Example:
- st$ = "This is a test of fast screen printing"
- row% = 10: col% = 20
- CALL Qprint(st$, row%, col%, attr%)
-
-
-
- Subroutine: QprintW(st$, row0%, col0%, row1%, col1%, attr%)
-
- QprintW adds word wrap to Qprint. Text will be confined to a
- window of the screen defined by ROW0%, COL0%, ROW1%, COL1%, and each line
- of text will be broken between words unless the word is longer than
- the width of the window, when the word will be broken at the edge of
- the window. QprintW also clears the window before Qprinting the text.
- If st$ = "", QprintW will clear the window and return to QuickBASIC.
-
- Example:
- st$ = "This is a test of fast screen printing with word wrap"
- row0% = 10: col0% = 20: row1% = 15: col1% = 50
- CALL QprintW(st$, row0%, col0%, row1%, col1%, attr%)
- Subroutine: Qread(st$, row%, col%)
-
- Uses DVMT to read a string of text from the active video page.
- The initial length of st$ determines the length of the string returned
- by Qread. This is like Qprint in reverse.
-
- Example:
- st$ = SPACE$(14)
- row% = 12
- col% = 5
- CALL Qread(st$, row%, col%)
- REM st$ is now the first 14 characters on the active video page
- REM beginning at row 12, column 5
-
-
-
- Subroutine: Qscroll(row0%, col0%, row1%, col1%, attr%, lines%)
-
- A DVMT window scroll routine. The area scrolled is limited by row0%,
- col0%, row1%, col1%. Positive values of lines% will scroll the screen up,
- negative values scroll the screen down, and lines% = 0 will blank the
- block of the screen. Rows cleared by the scrolling action will be set to
- color attribute attr%.
-
- Example:
- row0% = 5
- col0% = 10
- row1% = 15
- col1% = 75
- lines% = 1
- CALL Qscroll(row0%, col0%, row1%, col1%, attr%, lines%)
- REM we just scrolled a block of the screen one row up
- Subroutine: ReColorWindow(row0%, col0%, row1%, col1%, oldattr%, newattr%)
-
- Replaces oldattr% color with newattr% in the window defined by
- row0%, col0%, row1%, col1%, without re-printing the contents of the
- window.
-
- Example:
- oldattr% = 7 ' gray on black to be replaced
- newattr% = 14 ' with bright red on black
- row0% = 10: col0% = 1 ' from row 10, column 1
- row1% = 25: col1% = 80 ' to the end of the screen
- CALL ReColorWindow(row0%, col0%, row1%, col1%, oldattr%, newattr%)
-
-
-
- Subroutine: SaveScreen(scrnSEG%, scrnOFF%, direction%)
-
- Uses DVMT to save/restore display screen video page set by SetQPage
- in an array. Requires an array of 4000 bytes to save the screen (see
- example). Will check for retrace on CGA monitors to prevent "snow".
- Text mode only.
-
- Example:
- DIM scrn%(1999) ' 4000-byte array
- REM direction% <> 0 to save screen
- REM direction% = 0 to restore screen
- scrnSEG% = VARSEG(scrn%(0))
- scrnOFF% = VARPTR(scrn%(0))
- CALL SaveScreen(scrnSEG%, scrnOFF%, direction%)
-
-
-
- Subroutine: SetQPage(page%)
-
- Sets active video page used by most DVMT video routines.
-
- Example:
- page% = 2
- CALL SetQPage(page%)
- REM Qread, SaveScreen, PaintWindow, ClrScreen,
- REM ClrBlock, Qscroll, ReColorWindow and the Qprint series
- REM will now use screen page 2.
- EQUIPMENT routines detect the presence or status of PC hardware. Monitor
- type, co-processor presence, CPU speed and keyboard toggles may be
- determined, CPU speed toggle and keyboard toggles may be set. CTRL,
- ALT and SHIFT key status may also be monitored.
-
-
-
- Subroutine: ShiftKey(kbd%)
-
- Returns the status of the keyboard toggles and whether the CTRL, ALT
- or SHIFT keys are pressed. The code returned by ShiftKey is a copy of
- the BIOS keyboard status byte, which must be ANDed to determine which key
- toggles are set. See explanation of keyboard status byte in Appendix B.
-
- Example:
- rshift% = 1: lshift% = 2: shiftkey% = 3: ctrl% = 4: alt% = 8
- scroll% = 16: numb% = 32: caps% = 64: insert% = 128
-
- CALL ShiftKey(kbd%)
- IF (kbd% AND Rshift%) THEN PRINT "Right Shift pressed"
- IF (kbd% AND Lshift%) THEN PRINT "Left Shift pressed"
- IF (kbd% AND shiftkey%) THEN PRINT "Shift Key pressed"
- IF (kbd% AND ctrl%) THEN PRINT "Ctrl Key pressed"
- IF (kbd% AND alt%) THEN PRINT "Alt Key pressed"
- IF (kbd% AND scroll%) THEN PRINT "ScrollLOCK ON"
- IF (kbd% AND numb%) THEN PRINT "NumLOCK ON"
- IF (kbd% AND caps%) THEN PRINT "CapsLOCK ON"
- IF (kbd% AND insert%) THEN PRINT "INSERT ON"
-
-
-
- Subroutine: SetKeyToggle(kbd%)
-
- Sets the NumLOCK, CapsLOCK, ScrollLOCK and INSERT keyboard toggles.
- See examples in Appendix B, "KEYBOARD STATUS BYTE".
-
- Example:
- REM let's be sure the NumLOCK toggle is ON and CapsLOCK is off
- scroll% = 16: numb% = 32: caps% = 64: insert% = 128
- CALL GetKeyToggle(kbd%) ' get present toggles
- kbd% = (kbd% OR numb%) ' this will set NumLOCK ON
- kbd% = (kbd% AND (NOT caps%)) ' clears CapsLOCK bit
- CALL SetKeyToggle(kbd%)
-
-
-
- Subroutine: Get8087(CHIPEXISTS%)
-
- Detects the presence of a math coprocessor in the system.
- Value returned = -1 if 80x87 is present, 0 if not.
-
- Example:
- CALL Get8087(CHIPEXISTS%)
- IF chipexists% = -1 THEN PRINT "80x87 installed" Subroutine: KbdType
-
- Detects enhanced (101-key) keyboards on IBM or clones.
- Returns 1 if 101-key keyboard present, 0 if not.
-
- Example:
- CALL KbdType(a%)
- IF a% THEN PRINT "Enhanced keyboard attached to system"
-
-
-
- Subroutine: GetCRT(crt%)
-
- Tells you what kind of display is being used. The returned value
- will be zero if it's MDA, &H80 if Hercules, -1 if CGA, +1 if EGA.
-
- Example:
- CALL GetCRT(crt%)
- SELECT CASE crt%
- CASE -1
- PRINT "CGA Color"
- CASE 0
- PRINT "Monochrome Display Adapter"
- CASE 1
- PRINT "EGA Color"
- CASE &H80 ' &H80 = 128
- PRINT "Hercules"
- END SELECT
-
-
-
- Subroutine: GetSPEED(speed%)
-
- Determines whether the system is in "turbo" mode. Returns 0 if
- CPU is operating at normal speed, 1 if operating at faster CPU speed.
- See also SetSPEED.
-
- Example:
- CALL GetSpeed(speed%)
-
-
-
- Subroutine: SetSPEED(speed%)
-
- Sets speed toggle of most "turbo" clone computers. SPEED% = 0 will
- set normal CPU speed, any other value for SPEED% will set "turbo" speed.
- Should not affect non-turbo computers (such as IBM PC, AT, etc.). Good
- style suggests that before using this function for the first time, you
- should get the initial speed with GetSPEED and save it. You should
- then restore the CPU to that original state before exiting the program.
-
- Example:
- CALL SetSpeed(speed%)
- INPUT routines replace INKEY$ commands
-
-
- Subroutine: GetAKey(a%. extended%)
-
- Returns the ASCII character code of the first keypress waiting in the
- keyboard buffer. If extended% = -1, then the key pressed is an extended
- keycode (such as the function keys F1 - F10) and a% is the ASCII code of
- the second character of the keycode. If the key pressed is not an
- extended key, then extended% = 0. If no keypresses are waiting in the
- keyboard buffer, GetAKey waits until a key is pressed before it returns
- to QuickBASIC.
-
- Example:
- CALL GetAKey(a%, extended%)
- PRINT chr$(a%);" was pressed"
-
-
-
- Subroutine: KeyWaiting(a%)
-
- Uses BIOS calls to determine whether a key is waiting in the keyboard
- buffer, without reading the key.
-
- Example:
- CALL KeyWaiting(a%)
- IF a% = -1 THEN PRINT "A key has been pressed"
-
-
-
- Subroutine: YesNo(a%)
-
- Waits for either "Y" or "N" to be pressed, then returns the ASCII
- character code of the key pressed. The character code returned will be
- the code for UPPER case "Y" or "N", regardless of whether the key pressed
- was upper or lower case.
-
- Example:
- PRINT "Are you sure? (Y/N)"
- CALL YesNo(a%)
- REM ASC("Y") = 89, ASC("N") = 78
- IF a% = 89 THEN
- . ' instructions for Y response
- .
- .
- ELSE
- . ' instructions for N response
- .
- .
- END IF
- DATA routines manipulate numeric or string data. Single data points
- or portions of arrays may be shifted left or right (equivalent to
- multiplying or dividing by powers of 2), integers may be added to selected
- array elements, or arrays may be multiplied by real-number constants.
- INSTR-like functions find the LAST match of a sub-string in a string, or
- count the number of matches of a sub-string in a string. QLIB Array
- subroutines are MUCH faster and more compact than equivalent QuickBASIC
- FOR ... NEXT loops.
-
-
- Subroutine: AddINTArray(arSEG%, arOFF%, n%, value%, oops%)
- Subroutine: AddLNGArray(arSEG%, arOFF%, n%, value%, oops%)
-
- Adds an integer to the first n% elements of an integer or long
- integer array. You can subtract by adding a negative number. If the
- results of the calculation ever go outside integer range (-32768 to
- 32767) or long integer range (-2147483648 to 2147483647), oops% is set
- on return. AddLNGArray does NOT work with QB2 or QB3.
-
- Example:
- DIM Array1%(10000)
- .
- .
- value% = -6: n% = 1000
- arSEG% = VARSEG(Array1%(0)) ' arSEG = segment where array located
- arOFF% = VARPTR(Array1%(0)) ' arOFF = offset of array in segment
- CALL AddINTArray(arSEG%, arOFF%, n%, value%, oops%)
- IF oops% THEN PRINT "Uh oh, overflowed somewhere..."
- REM we just subtracted six from the first 1000 elements of the array
- REM Array1().
- REM Use AddLNGArray when adding a value to a long integer array
- REM Array1&()
-
-
-
- Subroutine: CopyMem(fromSEG%, fromOFF%, toSEG%, toOFF%, bytes%, crt%)
-
- Copies data from one part of memory to another. You supply
- the source segment and offset, destination segment and offset, and
- number of bytes to move (0 - 32767). This can be used to duplicate
- numeric arrays, or to copy to or from the video buffer. CopyMem will
- wait for retrace periods before copying any data if crt% = -1 (to avoid
- "snow" when copying to or from CGA video memory).
-
- Example:
- DIM Array1%(1999) ' 4000-byte array
- CALL GetCRT(crt%) ' crt% = -1 if monitor = CGA
- fromSEG% = &HB800 ' CGA / EGA video memory segment
- fromOFF% = 0 ' start of video memory buffer
- toSEG% = VARSEG(Array1%(0))
- toOFF% = VARPTR(Array1%(0))
- bytes% = 4000 ' 25 rows x 160 bytes per row
- CALL CopyMem(fromSEG%, fromOFF%, toSEG%, toOFF%, bytes%, crt%)
- REM we just stored the entire screen in array Array1%() Subroutine: CountInString(search$, pattern$, count%)
-
- Counts the number of times pattern$ is found in search$.
-
- Example:
- search$ = "This is a test string"
- pattern$ = "is"
- CALL CountInString(search$, pattern$, count%)
- REM count% = 2 in this example
- PRINT "pattern found "; count%; " times"
-
-
- Subroutine: InString(search$, pattern$, start%, position%)
-
- Similar to QuickBASIC's INSTR function, with additional
- flexibility. InString will find the first occurrence of pattern$ in
- search$, and will return position% = position in search$ where pattern$
- matches. InString will optionally search for the LAST occurrence of
- the pattern string in the search string, if start% is a negative number.
- If start% = 0, InString will return the number of matches of pattern$ in
- search$. LEN(pattern$) must be less than the portion of search$ to be
- searched.
-
- Example:
- search$ = "This is a test string"
- pattern$ = "is"
- start% = 1 ' begin search at first char in Search$
- CALL InString(search$, pattern$, start%, position%)
- ' returns position% = 3
-
- start% = 4 ' begin search at fourth char in Search$
- CALL InString(search$, pattern$, start%, position%)
- ' returns position% = 6
-
- start% = -(len(search$)) ' search for LAST match
- CALL InString(search$, pattern$, start%, position%)
- ' returns position% = 6
-
- start% = -4 ' search for LAST complete match in first
- ' 4 characters of search$
- CALL InString(search$, pattern$, start%, position%)
- ' returns position% = 3
-
- start% = 25 ' Starting position > LEN(search$)
- CALL InString(search$, pattern$, start%, position%)
- ' returns position% = 0
-
- start% = 0
- CALL InString(search$, pattern$, start%, position%)
- ' returns position% = 2
-
- Subroutine: MaxINTArray(aSEG%, aPTR%, n%, element%)
- Subroutine: MinINTArray(aSEG%, aPTR%, n%, element%)
-
- Finds array element with maximum or minimum value between begin%
- and begin% + n%. The array must be an INTEGER array.
-
- Example:
- DIM a%(99) ' 100 element array
- begin% = 0 ' start with the first array element
- n% = 90 ' look at the first 90 array elements
- aSEG% = VARSEG(a%(begin%))
- aPTR% = VARPTR(a%(begin%))
- CALL MaxINTArray(aSEG%, aPTR%, n%, element%)
- PRINT "the maximum value is"; a%(element% + begin%)
-
-
-
- Subroutine: MaxLNGArray(aSEG%, aPTR%, n%, element%)
- Subroutine: MinLNGArray(aSEG%, aPTR%, n%, element%)
-
- Finds array element with maximum or minimum value between begin%
- and begin% + n%. Works only with LONG INTEGER arrays. Will not work
- with QB2 or QB3.
-
- Example:
- DIM a&(99) ' 100 element LONG INTEGER array
- begin% = 0 ' start with the first array element
- n% = 90 ' look at the first 90 array elements
- aSEG% = VARSEG(a&(begin%))
- aPTR% = VARPTR(a&(begin%))
- CALL MaxLNGArray(aSEG%, aPTR%, n%, element%)
- PRINT "the maximum value is"; a&(element% + begin%) Subroutine: MulINTArray(aSEG%, aPTR%, n%, number!)
- Subroutine: MulLNGArray(aSEG%, aPTR%, n%, number!)
- Subroutine: MulSNGArray(aSEG%, aPTR%, n%, number!)
- Subroutine: MulDBLArray(aSEG%, aPTR%, n%, number#)
-
- MulArray subroutines multiply n% elements of an array
- by a constant real number. MulArray subroutines use the 8087 if
- present, or uses QuickBASIC's floating point emulator if the 8087 is
- not present. MulArray subroutines will NOT work with QB2 or QB3, but
- may work with QB87.
-
- MulINTArray is used if the array is a normal INTEGER array a%().
- MulLNGArray is used if the array is a LONG INTEGER array a&().
- MulSNGArray is used if the array is a real number array a!().
- MulDBLArray is used if the array is a double-precision real number
- array a#(). In this case the constant multiplied by the array is a
- double-precision real number (number#).
-
- Note that aSEG% and aPTR% are integers, and for all MulArray routines
- other than MulDBLArray, number! is a single-precision real number.
-
- Example:
- DIM a#(99) ' 100-element array, double precision
- .
- .
- .
- number# = 4.78
- n% = 50 ' multiply a#(0) through a#(49) by number#
- aSEG% = VARSEG(a#(0)) ' aSEG% = segment where a#(0) is stored
- aPTR% = VARPTR(a#(0)) ' aPTR% = offset of a#(0) in aSEG%
- CALL MulDBLArray(aSEG%, aPTR%, n%, number#)
-
-
-
- Subroutine: Today(month%, day%, year%, dayofweek%)
-
- Returns integer values for month (1 - 12), day of month (1 - 31),
- year (1980 - 2099), and day of week (1 - 7, Sunday through Saturday)
- from the system clock.
-
- Example:
- CALL Today(month%, day%, year%, dayofweek%) Subroutine: SetINTArray(ArSEG%, ArLOC%, SIZ%, SetVAL%, oops%)
- Subroutine: SetLNGArray(ArSEG%, ArLOC%, SIZ%, SetVAL%, oops%)
-
- Set the first SIZ elements of an integer array or a long integer
- array to an integer value. QB2 and QB3 do not support long integers.
-
- Example:
- OPTION BASE 1: DIM ACK%(10000): SIZ%=10000
- .
- .
- SetVAL%=-6
- ArSEG% = VARSEG(ACK%(1))
- ArLOC% = VARPTR(ACK%(1))
- CALL SetINTArray(ArSEG%, ArLOC%, SIZ%, SetVAL%, oops%)
- REM we just set each element of the array ACK to -6
-
- Example:
- OPTION BASE 1: DIM ACK&(10000): SIZ = 1000
- .
- .
- SetVAL% = 14
- ArSEG% = VARSEG(ACK&(1))
- ArLOC% = VARPTR(ACK&(1))
- CALL SetLNGArray(ArSEG%, ArLOC%, SIZ%, SetVAL%, oops%)
- REM we just set the first 1000 elements of the array ACK to 14
-
-
-
- Subroutine: Shift(value%, factor%)
- Subroutine: ShiftLong(value&, factor%)
-
- Shifts all the bits in an integer factor% times, putting zeroes
- in the bit positions which have been vacated. If factor% is positive,
- the bits are shifted LEFT. This effectively multiplies the value by a
- power of two in most instances. If factor% is negative, the bits are
- shifted RIGHT ABS(factor%) times. This is similar in effect to an integer
- divide by a power of two. SHIFT is used for 2-byte integers (VALUE%),
- SHIFTLONG is used for 4-byte LONG integer values (VALUE&). QB2 and QB3
- do not support long integers.
-
- Example:
- VALUE% = 47: factor% = 3
- CALL Shift(VALUE%, factor%)
- REM we just shifted VALUE% left three bits
- REM (in this case getting 47 * 2^3, or 376)
- Example:
- VALUE% = 47: factor% = -3
- CALL Shift(VALUE%, factor%)
- REM we just shifted VALUE% right 3 bits
- REM (here getting 47 \ 2^3, or 5)
- Subroutine: ShiftINTArray(aSEG%, aPTR%, n%, factor%, OOPS%)
- Subroutine: ShiftLNGArray(aSEG%, aPTR%, n%, factor%, OOPS%)
-
- Description:
- Shifts the bits of any n% elements of an integer array
- ABS(factor%) times, putting zeros in the bit positions which have been
- vacated. Positive values of factor% shift array elements LEFT. This
- is equivalent to multiplying the element by a factor% power of 2 in most
- instances. Negative values of factor% cause an integer divide by a
- ABS(factor%) power of 2. ShiftLNGArray should be used if the array is
- 4-byte long integers. OOPS% will be returned -1 if an overflow occurred.
- QB2 and QB3 do not support long integers.
-
- Example:
- DIM a%(100)
- n% = 20
- factor% = 1
- aSEG% = VARSEG(a%(0))
- aOFF% = VARPTR(a%(0))
- CALL ShiftINTArray(aSEG%, aOFF%, n%, count%, OOPS%)
- if OOPS% = -1 then PRINT "Oops, must have overflowed somewhere"
- REM we just shifted a%(0) through a%(19) one bit to the left
-
- DISK / FILE routines look for specified files on your disk, or report
- disk status.
-
-
- Subroutine: DriveSpace(drv$, total&, free&, oops%)
-
- Returns the amount of total and free space left on a given disk
- drive. The drive string may be any legal disk drive, or "@" (AT sign)
- for the default drive, and must be at least one character long. An
- illegal drive or other error will cause oops% to be returned as -1.
- Note that total& and free& are LONG integers. Works with logical devices
- up to 2,147 Megabytes. DriveSpace will NOT work with QB2 or QB3.
-
- Example:
- drv$="C:"
- .
- .
- CALL DriveSpace(drv$, total&, free&, oops%)
- IF oops% = -1 THEN
- PRINT "Invalid drive specification"
- ELSE
- PRINT "Free space on drive "; drv$; " is"; free&; "bytes."
- PRINT "Total space on drive "; drv$; " is"; total&; "bytes."
- END IF
-
-
-
- Subroutine: EXIST
-
- Tells you if a given file already exists. Returns an error code
- if it doesn't, or -1 if it does. Requires an ASCIZ filename without
- wildcards.
-
- Example:
- FIL$="TEST.TXT" + CHR$(0)
- CALL EXIST(FIL$,Errcode%)
- IF Errcode% = -1 THEN PRINT "File already exists"
- IF Errcode% = 0 THEN PRINT "Path exists"
- ' FIL$ = "d:\path" + CHR$(0)
- IF Errcode% = 2 THEN PRINT "Path found, file not found"
- IF Errcode% = 3 THEN PRINT "Path or file not found"
- Subroutine: GetSUB(d$, sub$, sublen%)
-
- Gets the current directory on disk d$. The subdirectory string must
- be 64 characters long. Note that the returned string will NOT be started
- by a backslash "\" character - you should add one if appropriate. To get
- the current directory on the default drive, set d$ = "@". If d$ specifies
- an invalid drive, sublen$ will be returned -1. NOTE: d$ must be at least
- one character long.
-
- Example:
- sub$ = SPACE$(64)
- d$ = "C"
- CALL GetSUB(d$, sub$, sublen%)
- IF sublen% = -1 THEN
- PRINT d$ + " is not a valid drive"
- ELSE
- sub$ = "\" + LEFT$(sub$, sublen%)
- END IF
-
-
-
- Subroutine: GetDRIVE(drv%)
-
- Returns the ASCII character code of the default drive.
-
- Example:
- CALL GetDRIVE(drv%)
- drive$ = CHR$(drv%)+":"
- PRINT "The default drive is "; drive$
-
-
-
- Subroutine: SetDRIVE(d$)
-
- Sets d$ as the default drive. D$ may be any valid disk drive or
- other logical device (such as a RAMdisk).
-
- Example:
- d$ = "a:" ' the drive specifier d$ may be upper or lower
- ' case and need not include the colon.
- CALL SetDRIVE(d$) ' drive A: is now the default drive
- APPENDIX A - Color attributes for video displays
-
- Colors values for IBM (and compatible) color displays are as follows:
-
- Color Value notes
-
- black 0 high-intensity black = gray
- blue 1
- green 2
- cyan 3
- red 4
- magenta 5
- brown 6 high-intensity brown = yellow
- "white" 7 normal-intensity "white" looks muddy
-
-
- For IBM Monochrome, Hercules and compatible displays:
-
- foreground value appearance
-
- 0 black if background% = 0 or 7
- if background% between 1 and 6,
- normal if bright% = 0
- bright if bright% = 1
-
- 1 underlined bright + underline
- if bright% = 1
-
- 2 - 7 normal bright if bright% = 1
-
- background value appearance
-
- 0 - 6 black
- 7 normal color if foreground% = 0
-
- bright if blink% = 1, SetBLINK(0)
- called, and foreground% = 0
-
- black if foreground% <> 0
- APPENDIX B - KEYBOARD STATUS BYTE
- Subroutines ShiftKey and SetKeyToggle
-
- The keyboard status byte consists of 8 bits, 4 of which are used
- to indicate the status of the INSERT, CapsLOCK, NumLOCK and ScrollLOCK
- keys. For each of these keys, one bit is set ( =1 ) if the key is
- toggled ON. The bit is zeroed if the key is OFF.
-
- The keyboard status byte:
- <--- bit positions -->
- 7 6 5 4 3 2 1 0
- │ │ │ │ │ │ │ └ 1 = Right shift pressed
- │ │ │ │ │ │ └─── 1 = Left shift pressed
- │ │ │ │ │ └────── 1 = either Control pressed
- │ │ │ │ └──────────1 = either Alt pressed
- │ │ │ └─────────────1 = ScrollLOCK active
- │ │ └────────────────1 = NumLOCK active
- │ └───────────────────1 = CapsLOCK active
- └──────────────────────1 = INSERT active
-
- BASIC does not understand individual bits, but armed with a little
- knowledge, you can out-think BASIC. BASIC interprets each bit as a
- power of 2, so that
- bit 0 if on = 1
- bit 1 if on = 2
- bit 2 if on = 4
- bit 3 if on = 8
- bit 4 if on = 16
- bit 5 if on = 32
- bit 6 if on = 64
- bit 7 if on = 128
-
- Thus, if NumLOCK and CapsLOCK are active, but ScrollLOCK and INSERT are
- off, BASIC will tell you that the keyboard status byte = 32 + 64 = 96
- (this is bit 5 and bit 6 ON, all other bits off). After calling
- ShiftKey, you may determine which key or keys are ON by ANDing the
- status byte with the value associated with that key's bit.
-
- Example: Let's assume that NumLOCK and ScrollLOCK are ON, INSERT and
- CapsLOCK are off.
-
- CALL ShiftKey(kbd%)
- PRINT kbd% ' prints 48 (results from 16+32)
- IF (kbd% AND 16) THEN PRINT "ScrollLOCK ON"
- IF (kbd% AND 32) THEN PRINT "NumLOCK ON"
- IF (kbd% AND 64) THEN PRINT "CapsLOCK ON" ' will not be printed
- in this example
- IF (kbd% AND 128) THEN PRINT "INSERT ON" ' will not be printed
- in this example
-
- The keyboard toggles may be stored as a single integer (kbd%) in
- order to restore the original status at a later time.
-
- Setting the keyboard toggles involves setting the individual bits
- in the status byte. The AND, OR and NOT operators come in handy
- here.
-
- OR compares the bits in both operands and sets all bits in the resulting
- byte corresponding to the bits in the operands.
-
- Example: set a keyboard toggle
-
- bits in operand a 0 0 1 0 0 0 0 0 (bit 5 set, = 32)
- operand b 1 0 0 1 0 0 0 0 (bits 4 and 7 set)
- ───────────────
- a OR b 1 0 1 1 0 0 0 0 ( bits 4, 5, and 7 set)
-
- In this way, an individual toggle may be added to kbd% and set via
- SetKeyToggle. If bit 5 had already been set in operand b, the result
- would be the same.
-
- Example: turn a keyboard toggle off
-
- bits in operand a 0 0 1 0 0 0 0 0 (bit 5 set, = 32)
- NOT a 1 1 0 1 1 1 1 1 (NOT reverses all bits)
- kbd% 1 0 1 1 0 0 0 0 ( a OR b, above)
- ───────────────
- (NOT a) AND kbd% 1 0 0 1 0 0 0 0
-
- As you can see, AND sets bits in the result only if the corresponding
- bits are set in BOTH operands. In this example, the bit in kbd% for
- NumLOCK is turned off. If SetKeyToggle is called with this new kbd%,
- NumLOCK will be turned off.
-
- APPENDIX C - QLIB and QB3
-
- This appendix applies to use of QLIB with QuickBASIC 2, QuickBASIC 3
- and QB3's QB87. QLIB was developed originally for QuickBASIC 4, but
- many of its subroutines may be used equally well with earlier versions
- of QuickBASIC. Any subroutines which I have found to be incompatible
- with earlier QuickBASICs are clearly marked in the description of each
- routine. As my time permits, I will modify those offending subroutines
- to enhance compatability of QLIB with all QuickBASIC versions. In most
- cases, this appendix applies equally to QB2 and QB3. I have not begun
- testing QLIB with QB3's QB87. I expect that the MulArray subroutines
- will work properly.
-
- Array Pointers
-
- Pointers to numeric arrays are passed to QLIB subroutines using
- those arrays. Both SEGMENT and OFFSET pointers must be passed, because
- many types of arrays are located outside QuickBASIC's default data
- segment.
-
- QuickBASIC 4 users have the VARSEG and VARPTR commands, which return an
- array's segment and offset, respectively, to QuickBASIC. Earlier versions
- of QuickBASIC lack the VARSEG command, but QLIB has two comparable
- routines which may be used with either QB3 or QB4.
-
- Subroutine: DataSEG(ds%)
-
- DataSEG returns QuickBASIC's default data segment, where static
- arrays are stored. ds% may be used along with QuickBASIC's VARPTR
- to address static arrays for QLIB array routines.
-
- Example:
- DIM a%(1999) ' 2000-byte static array
- .
- .
- .
- call DataSEG(ds%)
- aPTR% = VARPTR(a%(0))
- CALL ScreenSave(ds%, aPTR%, 1)
- REM this example saved the screen in array a% to recall later
-
-
-
- Subroutine: SegPTR(a(0), aSEG%, aPTR%)
-
- SegPTR returns both the segment and the offset pointers to a(0).
- a() may be any numeric array. aSEG% and aPTR% may be usd to address
- either static or dynamic arrays for QLIB array routines. Note that
- SegPTR is called using CALLS instead of CALL.
-
- Example:
- DIM a%(1999) ' 2000-byte array
- .
- .
- .
- CALLS SegPTR(a%(0), aSEG%, aPTR%)
- CALL ScreenSave(aSEG%, aPTR%, 1)
- REM this example saved the screen in array a% to recall later
-
-
- QB3 has a serious bug which creates a flawed object code when working
- within the QuickBASIC editor to create stand-alone .EXE files. To use
- QLIB to make stand-alone .EXE files, compile and link your programs from
- the DOS command line:
-
- to compile:
- QB yourprog /O;
-
- to link:
- LINK yourprog,,NUL,QLIB.LIB;
-
- QLIB will work fine when creating or debugging code within the QuickBASIC
- editor, but you must work from the DOS command line to make your stand-
- alone .EXE files.